/**
 * 
 */
package com.uobgroup.ews.uam.core.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.uobgroup.ews.uam.core.dao.AccessControlDao;
import com.uobgroup.ews.uam.core.dao.CombinationACLDao;
import com.uobgroup.ews.uam.core.dao.CombinationMatrixDao;
import com.uobgroup.ews.uam.core.dao.SecurityGroupDao;
import com.uobgroup.ews.uam.core.domain.AccessControl;
import com.uobgroup.ews.uam.core.domain.CombinationMatrix;
import com.uobgroup.ews.uam.core.domain.Reference;
import com.uobgroup.ews.uam.core.domain.SecurityGroup;
import com.uobgroup.ews.uam.core.model.CombiSecInfo;
import com.uobgroup.ews.uam.core.model.CombiSecInfoList;
import com.uobgroup.ews.uam.core.model.CombinationACLParamsName;

/**
 * @author phuongtran
 * 
 */

@Service
@Transactional
public class CombinationACLServiceImpl implements CombinationACLService {

   @Autowired
   CombinationMatrixDao combinationMatrixDao;

   @Autowired
   AccessControlDao accessControlDAO;

   @Autowired
   SecurityGroupDao securityGroupDAO;

   @Autowired
   CombinationACLDao combinationACLDao;

   /*
    * Phuong Tran
    */
   @Override
   public CombiSecInfoList getCaseSecurity(HashMap<String, List<String>> params) {
      List<CombinationMatrix> combinationLst = searchCombinationCaseByProperties(params);
      List<CombiSecInfo> combiSecInfoLst = buildCombiSecInfoList(combinationLst);
      if (combiSecInfoLst != null) {
         return new CombiSecInfoList(combiSecInfoLst);
      }
      else {
         return new CombiSecInfoList();
      }
   }

   /*
    * Phuong Tran
    */
   @Override
   public CombiSecInfoList getDocSecurity(HashMap<String, List<String>> params) {
      List<CombinationMatrix> combinationLst = searchCombinationDocByProperties(params);
      List<CombiSecInfo> combiSecInfoLst = buildCombiSecInfoList(combinationLst);
      if (combiSecInfoLst != null) {
         return new CombiSecInfoList(combiSecInfoLst);
      }
      else {
         return new CombiSecInfoList();
      }
   }

   /*
    * Phuong Tran
    */
   public List<CombinationMatrix> searchCombinationDocByProperties(HashMap<String, List<String>> params) {
      List<CombinationMatrix> lstCombination = new ArrayList<CombinationMatrix>();

      List<String> docTypeValues = new ArrayList<String>();
      List<String> countryValues = new ArrayList<String>();

      if (params.get(CombinationACLParamsName.DOC_TYPE) != null) {
         docTypeValues = params.get(CombinationACLParamsName.DOC_TYPE);
      }
      if (params.get(CombinationACLParamsName.COUNTRY) != null) {
         countryValues = params.get(CombinationACLParamsName.COUNTRY);
      }

      Iterator<String> itDocType = docTypeValues.iterator();
      while (itDocType.hasNext()) {
         String docType = itDocType.next();
         Iterator<String> itCountry = countryValues.iterator();
         while (itCountry.hasNext()) {
            String country = itCountry.next();
            List<CombinationMatrix> rawList = combinationMatrixDao.searchMadatoryDocProperties(docType, country);
            filterCombinationDocData(lstCombination, rawList, params);
         }
      }

      return lstCombination;
   }

   /*
    * Phuong Tran
    */
   public List<CombinationMatrix> searchCombinationCaseByProperties(HashMap<String, List<String>> params) {
      List<CombinationMatrix> lstCombination = new ArrayList<CombinationMatrix>();

      List<String> processingCenterValues = new ArrayList<String>();
      List<String> transactionTypeValues = new ArrayList<String>();
      List<String> countryValues = new ArrayList<String>();

      if (params.get(CombinationACLParamsName.PROCESSING_CENTER) != null) {
         processingCenterValues = params.get(CombinationACLParamsName.PROCESSING_CENTER);
      }
      if (params.get(CombinationACLParamsName.TRANSACTION_TYPE) != null) {
         transactionTypeValues = params.get(CombinationACLParamsName.TRANSACTION_TYPE);
      }
      if (params.get(CombinationACLParamsName.COUNTRY) != null) {
         countryValues = params.get(CombinationACLParamsName.COUNTRY);
      }

      Iterator<String> itProcessingCenterType = processingCenterValues.iterator();
      while (itProcessingCenterType.hasNext()) {
         String processingCenterType = itProcessingCenterType.next();
         Iterator<String> itTransType = transactionTypeValues.iterator();
         while (itTransType.hasNext()) {
            String transType = itTransType.next();
            Iterator<String> itCountry = countryValues.iterator();
            while (itCountry.hasNext()) {
               String country = itCountry.next();
               List<CombinationMatrix> rawList = combinationMatrixDao.searchMadatoryCaseProperties(
                     processingCenterType, transType, country);
               filterCombinationCaseData(lstCombination, rawList, params);
            }
         }
      }

      return lstCombination;
   }

   /*
    * Phuong Tran
    */
   public void filterCombinationDocData(List<CombinationMatrix> resultList, List<CombinationMatrix> rawList,
         HashMap<String, List<String>> params) {
      List<String> processingCenterList = params.get(CombinationACLParamsName.PROCESSING_CENTER);
      List<String> transactionTypeList = params.get(CombinationACLParamsName.TRANSACTION_TYPE);
      List<String> productTypeList = params.get(CombinationACLParamsName.PRODUCT_TYPE);
      List<String> userLocationList = params.get(CombinationACLParamsName.USER_LOCATION);

      Iterator<CombinationMatrix> itRaw = rawList.iterator();
      while (itRaw.hasNext()) {
         CombinationMatrix combiRaw = itRaw.next();
         if (isDataMatch(processingCenterList, combiRaw.getProcessingCentre())
               && isDataMatch(transactionTypeList, combiRaw.getTransactionType())
               && isDataMatch(productTypeList, combiRaw.getProductType())
               && isDataMatch(userLocationList, combiRaw.getUserLocation())) {
            resultList.add(combiRaw);
         }
      }
   }

   /*
    * Phuong Tran
    */
   public void filterCombinationCaseData(List<CombinationMatrix> resultList, List<CombinationMatrix> rawList,
         HashMap<String, List<String>> params) {
      List<String> docTypeList = params.get(CombinationACLParamsName.DOC_TYPE);
      List<String> productTypeList = params.get(CombinationACLParamsName.PRODUCT_TYPE);
      List<String> userLocationList = params.get(CombinationACLParamsName.USER_LOCATION);

      Iterator<CombinationMatrix> itRaw = rawList.iterator();
      while (itRaw.hasNext()) {
         CombinationMatrix combiRaw = itRaw.next();
         if (isDataMatch(docTypeList, combiRaw.getTransactionType())
               && isDataMatch(productTypeList, combiRaw.getProductType())
               && isDataMatch(userLocationList, combiRaw.getUserLocation())) {
            resultList.add(combiRaw);
         }
      }
   }

   private boolean isDataMatch(List<String> searchValues, Reference ref) {
      boolean ret = false;
      if (ref == null) {
         ret = true;
      }
      else {
         if (searchValues == null) {
            ret = true;
         }
         else {
            if (searchValues.contains(ref.getName())) {
               ret = true;
            }
         }
      }
      return ret;
   }

   private List<CombiSecInfo> buildCombiSecInfoList(List<CombinationMatrix> combinationLst) {
      List<CombiSecInfo> combiSecInfoLst = new ArrayList<CombiSecInfo>();

      if (combinationLst != null) {
         Iterator<CombinationMatrix> itCombinations = combinationLst.iterator();
         while (itCombinations.hasNext()) {
            CombinationMatrix combi = itCombinations.next();
            List<AccessControl> aclLst = combinationACLDao.findACLs(combi);
            if (aclLst != null) {
               Iterator<AccessControl> itACLs = aclLst.iterator();
               while (itACLs.hasNext()) {
                  AccessControl acl = itACLs.next();
                  SecurityGroup secGroup = combinationACLDao.findSecGroup(combi, acl);
                  if (secGroup != null) {
                     CombiSecInfo combiSecinfo = new CombiSecInfo(secGroup.getDN(), acl.getPermission());
                     combiSecInfoLst.add(combiSecinfo);
                  }
               }
            }
         }
      }

      return combiSecInfoLst;
   }

}
